package com.css.ids.server.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

import com.css.apps.base.dict.model.SDict;
import com.css.apps.base.func.model.SFunc;
import com.css.apps.base.menu.model.SMenu;
import com.css.apps.base.org.model.SOrg;
import com.css.apps.base.org.model.SOrgPost;
import com.css.apps.base.org.model.SUserOrg;
import com.css.apps.base.post.model.SPost;
import com.css.apps.base.post.model.SPostRole;
import com.css.apps.base.role.model.SRole;
import com.css.apps.base.role.model.SRoleFunc;
import com.css.apps.base.sys.model.SSys;
import com.css.apps.base.sysjob.model.SysJob;
import com.css.apps.base.user.leader.model.LeaderSecretary;
import com.css.apps.base.user.model.SUser;
import com.css.apps.base.user.model.SUserPost;
import com.css.apps.base.user.model.SUserRole;
import com.css.common.exception.base.CssBaseException;
import com.css.core.model.IServiceResult;
import com.css.core.model.ModeFactory;
import com.css.core.model.tree.Tree;
import com.css.core.model.tree.TreeCache;
import com.css.core.model.tree.TreeNode;
import com.css.db.memcached.MemCachedFactory;
import com.css.db.query.QueryCache;
import com.css.ids.server.service.IdsService;
import com.css.ids.server.service.dao.IdsDictDao;
import com.css.ids.server.service.dao.IdsFuncDao;
import com.css.ids.server.service.dao.IdsMenuDao;
import com.css.ids.server.service.dao.IdsOrgDao;
import com.css.ids.server.service.dao.IdsPostDao;
import com.css.ids.server.service.dao.IdsRoleDao;
import com.css.ids.server.service.dao.IdsSysDao;
import com.css.ids.server.service.dao.IdsSysJobDao;
import com.css.ids.server.service.dao.IdsUserDao;
import com.css.ids.server.util.CheckCodeUtil;
import com.css.ids.server.util.MenuUtil;
import com.css.util.ListUtil;
import com.css.util.Md5Util;
import com.css.util.Messages;
import com.css.util.StringHelper;
import com.css.util.UuidUtil;
import com.css.webbase.menu.MenuItem;

import net.sf.json.JSONObject;

/**
 * 
 * @author liuhy 2019 2019年3月3日
 *
 */
public class DefaultIdsService implements IdsService {

	// -----------------------------------------------------------------------------USER
	@Override
	public SUser getAuth(String loginName, String sysId) {
		if (StringHelper.isEmpty(loginName)) {
			return null;
		}
		SUser suser = IdsUserDao.getUserByLoginName(loginName);
		IdsUserDao.loadUserAuth(suser, sysId);
		return suser;
	}

	@Override
	public SUser getUser(String userId) {
		if (StringHelper.isEmpty(userId)) {
			return null;
		}
		SUser suser = null;
		try {
			suser = IdsUserDao.getUserByUserId(userId);
		} catch (Exception e) {
			if (suser == null) {
				System.out.println("the userId [" + userId + "] isnot exist.");
			} else {
				e.printStackTrace();
			}
		}
		return suser;
	}

	@Override
	public List<SUser> listUsersByConditions(Map<String, Object> conditions) {
		if (conditions == null) {
			return null;
		}
		return IdsUserDao.getUserByFilter(conditions);
	}

	@Override
	public List<SUser> listUsersByName(String userName) {
		if (StringHelper.isEmpty(userName)) {
			return null;
		}
		List<SUser> suserList = IdsUserDao.listUsersByName(userName);
		if (suserList == null || suserList.isEmpty()) {
			return null;
		}
		return suserList;
	}

	@Override
	public List<SUser> listUsersByDept(String deptId, boolean withChildren) {
		if (StringHelper.isEmpty(deptId)) {
			return null;
		}
		List<SUser> suserList = IdsUserDao.listUsersByDept(deptId, withChildren);
		return suserList;
	}

	@Override
	public List<SUser> listUsersByOrgPost(String orgId, String postId) {
		if (StringHelper.isEmpty(orgId) || StringHelper.isEmpty(postId)) {
			return null;
		}
		List<SUser> suserList = IdsUserDao.listUsersByOrgPost(orgId, postId);
		return suserList;
	}

	@Override
	public List<SUser> listUsersByParentOrgPost(String orgId, String postId) {
		if (StringHelper.isEmpty(orgId) || StringHelper.isEmpty(postId)) {
			return null;
		}
		List<SUser> userList = IdsUserDao.queryUsersByParentOrgPost(orgId, postId);
		if (userList == null) {
			return null;
		}
		return userList;
	}

	@Override
	public List<SUser> syncUsers(Date time, String sysId) {
		List<SUser> suserList = IdsUserDao.syncUsers(time, sysId);
		if (suserList == null || suserList.isEmpty()) {
			return null;
		}
		return suserList;
	}

	@Override
	public SUser getValidUser(String loginName, String loginPwd) {
		if (StringHelper.isEmpty(loginName) || StringHelper.isEmpty(loginPwd)) {
			return null;
		}
		String password = Md5Util.MD5Encode(Md5Util.MD5Encode(loginPwd));
		return IdsUserDao.getUserByLoginName(loginName, password);
	}

	@Override
	public boolean updUsers(Map<String, Map<String, Object>> conditions) {
		if (conditions == null) {
			return false;
		}
		return IdsUserDao.updUsers(conditions);
	}

	@Override
	public List<SUser> listUsers(Collection<String> userIds) {
		return IdsUserDao.listUsers(userIds);
	}
	
	@Override
	public List<SUser> listAllUser() {
		return IdsUserDao.listAllUser();
	}

	@Override
	public List<SUser> listCorporationAllUser(String corpId) {
		return IdsUserDao.listCorporationAllUser(corpId);
	}

	@Override
	public List<SUser> listAllUser(int orgLevel) {
		return IdsUserDao.listAllUser(orgLevel);
	}

	@Override
	public List<SUser> listUsersBySecondOrgPost(String secondOrgId, String postId) {
		if (StringHelper.isAnyEmpty(secondOrgId, postId)) {
			return null;
		}
		return IdsUserDao.listUsersBySecondLevelPost(secondOrgId, postId);
	}

	@Override
	public List<SUser> listUsersBySysAndOrg(List<String> sysList, List<String> orgList) {
		if (ListUtil.isLstEmpty(sysList) && orgList == null) {
			return null;
		}
		return IdsUserDao.queryUsersBySysAndOrg(sysList, orgList);
	}

	@SuppressWarnings("unchecked")
	@Override
	public IServiceResult<JSONObject> addOrUpdUser(SUser user, List<SysJob> sysjobList) {
		IServiceResult<JSONObject> res = null;
		ModeFactory factory = ModeFactory.getModeFactory();
		try {
			IdsUserDao.addOrUpdUser(user, sysjobList);
			res = factory.buildNewServiceResult(IServiceResult.RESULT_OK, Messages.getString("systemMsg.success"));
		} catch (CssBaseException e) {
			res = factory.buildNewServiceResult(IServiceResult.RESULT_FAILED, Messages.getString("systemMsg.failed"));
		}
		return res;
	}

	// ---------------------------------------------------------------------------ORG
	@Override
	public SOrg getOrg(String orgId) {
		if (StringHelper.isEmpty(orgId)) {
			return null;
		}
		SOrg org = IdsOrgDao.getOrg(orgId);
		if (org == null) {
			return null;
		}
		return org;
	}

	@Override
	public List<String> listOrgIds() {
		List<String> lst = null;
		Tree tree = new TreeCache(SOrg.class);
		List<TreeNode> nds = tree.getTree();
		if (nds != null && nds.size() > 0) {
			lst = new ArrayList<String>();
			for (TreeNode node : nds) {
				lst.add(node.getNodeId());
			}
		}
		return lst;
	}

	@Override
	public List<TreeNode> listOrgs(String dataType, String params) {
		String str[] = params.split("，"); // ，和：均为中文符号
		String prefix[] = new String[str.length];
		String res[] = new String[str.length];
		List<TreeNode> lst = new ArrayList<TreeNode>();
		Integer series = null;
		String parentId = null;
		TreeNode tn = null;
		Tree tree = new TreeCache(SOrg.class);
		// 拆分parms，得到自定义组织机构树的根节点和级数
		for (int i = 0; i < str.length; i++) {
			prefix[i] = str[i].split("：")[0];
			if ("series".equals(prefix[i])) {
				res[i] = str[i].split("：")[1];
				series = Integer.valueOf((res[i]));
			} else if ("parentOrgId".equals(prefix[i])) {
				res[i] = str[i].split("：")[1];
				parentId = (res[i]);
			}
		}
		if (parentId == null) {
			if (series == null) {
				tn = tree.getRoot().get(0);// 当前节点
			}
		} else {
			tn = tree.getTreeNode(parentId);// 当前节点
		}
		List<TreeNode> nds = tn.getChildren();// 当前节点的孩子
		for (int i = 1; i < series; i++) {
			lst.addAll(getChilds(nds));
			nds = getChilds(nds);
		}
		if (TYPE_ORG.ORG.equals(dataType)) {
			return lst;
		} else if (TYPE_ORG.ORG_USER.equals(dataType)) {
			// 给org挂在user
			return lst;
		} else if (TYPE_ORG.ORG_USER_POST.equals(dataType)) {
			// 给org挂在user和post
			return lst;
		}
		return lst;
	}

	/**
	 * 获取节点集合的子节点
	 *
	 * @param nds
	 * @return
	 */
	private List<TreeNode> getChilds(List<TreeNode> nds) {
		List<TreeNode> listAll = new ArrayList<TreeNode>();
		for (TreeNode node : nds) {
			if (!node.getChildren().isEmpty()) {// 若当前节点是父节点则接着获取当前节点的孩子节点
				List<TreeNode> list = node.getChildren();
				listAll.addAll(list);
			}
		}
		return listAll;
	}

	@Override
	public List<SOrg> listOrgs(Collection<String> orgIds) {
		return IdsOrgDao.listOrgs(orgIds);
	}

	@Override
	public List<SOrg> listAllOrg() {
		return IdsOrgDao.listAllOrg();
	}

	@Override
	public List<SOrg> syncOrgs(Date time) {
		List<SOrg> orgList = IdsOrgDao.syncOrgs(time);
		if (orgList == null || orgList.isEmpty()) {
			return null;
		}
		return orgList;
	}

	@Override
	public List<SOrg> listAllOrg(int orgLevel) {
		return IdsOrgDao.listAllOrg(orgLevel);
	}

	@Override
	public List<SOrg> listAllOrg(int orgLevel, String orgId, String orgType) {
		return IdsOrgDao.listAllOrg(orgLevel, orgId, orgType);
	}

	// ---------------------------------------------------------------------POST
	@Override
	public SPost getPost(String postId) {
		if (StringHelper.isEmpty(postId)) {
			return null;
		}
		SPost post = IdsPostDao.getPost(postId);
		if (post == null) {
			return null;
		}
		return post;
	}
	
	@Override
	public List<String> listPostsByNames(String... postNames) {
		if (postNames == null || postNames.length == 0) {
			return null;
		}
		return IdsPostDao.listPostsByNames(postNames);
	}
	
	@Override
	public List<SPost> listPosts(Collection<String> postIds) {
		return IdsPostDao.listPostsByIds(postIds);
	}

	@Override
	public List<SPost> listAllPost(boolean isGroup) {
		return IdsPostDao.listAllPost(isGroup);
	}

	// ---------------------------------------------------------------------------
	// MENU
	@Override
	public SMenu getMenu(String menuId) {
		if (StringHelper.isEmpty(menuId)) {
			return null;
		}
		SMenu menu = IdsMenuDao.getMenu(menuId);
		if (menu == null) {
			return null;
		}
		return menu;
	}

	@Override
	public List<com.css.apps.base.menu.model.MenuItem> listMenusByRole(String roleId, String sysId) {
		if (StringHelper.isEmpty(roleId) || StringHelper.isEmpty(roleId)) {
			return null;
		}
		SRole role = getRole(roleId);
		List<MenuItem> menuList = IdsMenuDao.listMenusByRole(role, sysId);
		if (menuList == null) {
			return null;
		}
		List<com.css.apps.base.menu.model.MenuItem> mis = transferMenuItem(null, menuList);
		return mis;
	}

	@Override
	public List<com.css.apps.base.menu.model.MenuItem> listMenus(String userId, String sysId) {
		if (StringHelper.isEmpty(userId) || StringHelper.isEmpty(sysId)) {
			return null;
		}
		SUser user = getUser(userId);
		IdsUserDao.loadUserAuth(user, sysId);
		List<MenuItem> menuList = MenuUtil.getUserMenuContent(user, sysId);
		if (menuList == null) {
			return null;
		}
		List<com.css.apps.base.menu.model.MenuItem> mis = transferMenuItem(null, menuList);
		return mis;
	}

	private List<com.css.apps.base.menu.model.MenuItem> transferMenuItem(com.css.apps.base.menu.model.MenuItem curRoot,
			List<MenuItem> menuList) {
		if (menuList != null) {
			List<com.css.apps.base.menu.model.MenuItem> mis = new ArrayList<com.css.apps.base.menu.model.MenuItem>();
			for (MenuItem menu : menuList) {
				com.css.apps.base.menu.model.MenuItem mi = new com.css.apps.base.menu.model.MenuItem();
				try {
					BeanUtils.copyProperties(mi, menu);
				} catch (IllegalAccessException | InvocationTargetException e) {
					e.printStackTrace();
				}
				mis.add(mi);
				List<MenuItem> subMenuList = menu.getMenus();
				if (subMenuList != null) {
					transferMenuItem(mi, subMenuList);
				}
			}
			if (curRoot != null) {
				curRoot.setMenus(mis);
			}
			return mis;
		}
		return null;
	}

	// -----------------------------------------------------------------------
	// DICT
	@Override
	public SDict getDictByTableCode(String table, String code) {
		if (StringHelper.isEmpty(table) || StringHelper.isEmpty(code)) {
			return null;
		}
		SDict dict = IdsDictDao.queryDictByTableCode(table, code);
		if (dict == null) {
			return null;
		}
		return dict;
	}

	@Override
	public List<SDict> listDictsByTable(String table) {
		if (StringHelper.isEmpty(table)) {
			return null;
		}
		List<SDict> dictList = IdsDictDao.queryDictsByTable(table);
		if (dictList == null) {
			return null;
		}
		return dictList;
	}

	@Override
	public List<SDict> listDicts(Collection<String> dictIds) {
		return IdsDictDao.getDicts(dictIds);
	}

	@Override
	public boolean checkPwd(String type, String userId, String password) {
		if (type.equals(TYPE_PWD.LOGIN)) {
			SUser user = IdsUserDao.getUserByLoginName(userId);
			if (user != null && user.getPassword().equals(password)) {
				return true;
			}
		} else if (type.equals(TYPE_PWD.REVIEW)) {
			SUser user = IdsUserDao.getUserByUserId(userId);
			if (user != null && password != null) {
				// 首先判断签章密码，没有签章密码再判断登录密码
				if (StringHelper.isNotEmpty(user.getReviewPwd()))
					return Md5Util.MD5Encode(password).equals(user.getReviewPwd());
				else
					return Md5Util.MD5Encode(password).equals(user.getPassword());
			}
		}
		return false;
	}

	@Override
	public String getCheckCode(String type, String userId) {
		if (StringHelper.isAnyEmpty(type)) {
			return null;
		}
		String code = null;
		if (TYPE_CHECKCODE.DDCODE.equals(type)) {
			code = UuidUtil.getUuid();
			MemCachedFactory.set(code, code, 6000);
		} else if (TYPE_CHECKCODE.CHECKCODE.equals(type)) {
			SUser user = IdsUserDao.getUserByUserId(userId);
			if (user == null) {
				return null;
			}
			code = CheckCodeUtil.generateCheckCode(6);
			MemCachedFactory.set(type + userId, code, 6000);
		} else if (TYPE_CHECKCODE.SIGN.equals(type)) {
			SUser user = IdsUserDao.getUserByUserId(userId);
			if (user == null) {
				return null;
			}
			code = UuidUtil.getUuid();
			MemCachedFactory.set(type + userId, code, 6000);
		}
		return code;
	}

	@Override
	public boolean checkCodeAuth(String type, String userId, String code) {
		if (StringHelper.isAnyEmpty(type, code)) {
			return false;
		}
		if (TYPE_CHECKCODE.DDCODE.equals(type)) {
			String ddcode = (String) MemCachedFactory.get(code);
			if (StringHelper.isNotEmpty(ddcode)) {
				return true;
			}
		} else if (TYPE_CHECKCODE.CHECKCODE.equals(type)) {
			SUser user = IdsUserDao.getUserByUserId(userId);
			if (user == null) {
				return false;
			}
			String checkcode = (String) MemCachedFactory.get(type + userId);
			if (StringHelper.isNotEmpty(checkcode) && code.equals(checkcode)) {
				return true;
			}
		} else if (TYPE_CHECKCODE.SIGN.equals(type)) {
			SUser user = IdsUserDao.getUserByUserId(userId);
			if (user == null) {
				return false;
			}
			String sign = (String) MemCachedFactory.get(type + userId);
			if (StringHelper.isNotEmpty(sign) && code.equals(sign)) {
				return true;
			}
		}
		return false;
	}

	// --------------------------------------------------------------------------ROLE
	@Override
	public SRole getRole(String roleId) {
		return IdsRoleDao.getRole(roleId);
	}
	
	@Override
	public List<SRole> listRoles(Collection<String> roleIds) {
		return IdsRoleDao.listRoles(roleIds);
	}

	@Override
	public List<SRole> listRolesByCondition(List<String> conditions) {
		return IdsRoleDao.listRolesByFilter(conditions);
	}

	// ---------------------------------------------------------------------------FUNC
	@Override
	public SFunc getFunc(String uuid) {
		return IdsFuncDao.getFunc(uuid);
	}
	
	@Override
	public List<SFunc> listFuncs(Collection<String> funcIds) {
		return IdsFuncDao.listFuncs(funcIds);
	}

	@Override
	public List<SFunc> listFuncsByUser(String userId, String sysId) {
		if (StringHelper.isEmpty(userId) && StringHelper.isEmpty(sysId)) {
			return null;
		}
		return IdsFuncDao.getFuncByUserId(userId, sysId);
	}

	// -----------------------------------------------------------------------------SYS
	@Override
	public SSys getSys(String sysId) {
		return IdsSysDao.getSys(sysId);
	}

	@Override
	public List<SSys> listSys(Collection<String> sysIds) {
		return IdsSysDao.listSys(sysIds);
	}
	
	@Override
	public List<SSys> listSys() {
		return IdsSysDao.getAllSys();
	}

	// -----------------------------------------------------------------------------SYSJOB
	@Override
	public List<SysJob> listSysJob(String orgId, String jobId) {
		if (StringHelper.isEmpty(orgId) || StringHelper.isEmpty(jobId)) {
			return null;
		}
		return IdsSysJobDao.getSysJobsByOrgIdAndJobId(orgId, jobId);
	}

	// -----------------------------------------------------------------------------RELATE

	@SuppressWarnings("unchecked")
	@Override
	public List<SUserOrg> listUserOrg() {
		return new QueryCache("from SUserOrg").list();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<SUserPost> listUserPost() {
		return new QueryCache("from SUserPost").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<SPostRole> listPostRole() {
		return new QueryCache("from SPostRole").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<SOrgPost> listOrgPost() {
		return new QueryCache("from SOrgPost").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<SRoleFunc> listRoleFunc() {
		return new QueryCache("from SRoleFunc").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<SUserRole> listUserRole() {
		return new QueryCache("from SUserRole").list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<LeaderSecretary> listLeaderSecretaries() {
		return new QueryCache("from LeaderSecretary").list();
	}

}
